/**
 *******************************************************************************
 *                 Copyright (C) 2017 - 2022  Accumulate Team                
 *                                                                           
 *      Licensed under the Apache License, Version 2.0 (the "License");      
 *      you may not use this file except in compliance with the License.     
 *      You may obtain a copy of the License at                              
 *                 http://www.apache.org/licenses/LICENSE-2.0                
 *                                                                           
 *   Unless required by applicable law or agreed to in writing, software     
 *   distributed under the License is distributed on an "AS IS" BASIS,       
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and     
 *   limitations under the License.                                          
 *******************************************************************************
 * @file       sm_core.c
 * @author     Accumulate Team
 * @version    1.0.0
 * @date       2018-12-13
 * @brief      framework state machine component source files
 * @par        work platform
 *                 Windows
 * @par        compiler
 *                 GCC
 *******************************************************************************
 * @note
 * 1. 20181213    创建文件
 *******************************************************************************
 */

/**
 * @defgroup framework state machine component
 * @{
 */

/* Includes ------------------------------------------------------------------*/
#include "sm_core.h"
#include <string.h>

//! include state mechine debug component
#if SM_APP_PALTFORM == 1
#include "port/rt-thread/sm_dbg.h"
#elif SM_APP_PALTFORM == 2
#include "port/freertos/sm_dbg.h"
#else
#include "port/ysf/sm_dbg.h"
#endif

/* Exported macro ------------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief       状态机SELF TIMER OPS 初始化参数
 *******************************************************************************
 */
#define SM_TIMER_OPS_INIT_PARAM \
{\
    .init  = _self_timer_init,\
    .start = _self_timer_start,\
    .stop  = _self_timer_stop,\
}

/**
 *******************************************************************************
 * @brief       状态机SELF EVENT FLAG OPS 初始化参数
 *******************************************************************************
 */
#define SM_EVENT_FLAG_OPS_INIT_PARAM \
{\
    .init          = _self_flag_init, \
    .set           = _self_flag_send, \
    .append        = _self_flag_filter_append, \
    .append_static = _self_flag_filter_append_static, \
    .fini          = _self_flag_filter_clear, \
}

/**
 *******************************************************************************
 * @brief       状态机SELF SIGNAL OPS 初始化参数
 *******************************************************************************
 */
#define SM_SIGNAL_OPS_INIT_PARAM \
{\
    .init                    = sm_sig_init, \
    .fini                    = sm_sig_fini, \
    .emit                    = sm_sig_emit, \
    .connect                 = sm_sig_connect_callback, \
    .connect_static          = sm_sig_connect_callback_static, \
    .connect_event           = sm_sig_connect_event, \
    .connect_event_static    = sm_sig_connect_event_static, \
    .disconnect              = sm_sig_disconnect, \
}

/* Exported types ------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/

/* Exported variables --------------------------------------------------------*/

/* Private functions ---------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief       状态机对象基本操作接口
 *******************************************************************************
 */
/**
 * @brief       获取SM对象句柄
 * @param       [in]   name     对象NAME
 * @param       [in]   index    对象ID
 * @return      [out]  SM 对象句柄
 * @note        sm component内部调用
 */
sm_obj_t *sm_obj_find(char *name)
{
    struct SM_CORE_HANDLE *handle = sm_core();

    sm_list_for_each_entry(obj, &handle->obj_list, sm_obj_t, list)
    {
        char *sm_name = sm_obj_name(obj);
        if (name != NULL && strcmp(sm_name, name) == 0)
        {
            handle->self->obj = obj;
            return obj;
        }
    }

    return NULL;
}

/**
 * @brief       状态机对象函数挂载到内核中
 * @param       [in]   *obj      状态机对象
 * @return      [out]  void
 * @note        None
 */
void sm_obj_append(sm_obj_t *obj)
{
    SM_ASSERT(obj);

    sm_list_append(&sm_core()->obj_list, &obj->list);
}

/**
 * @brief       状态机对象函数移除出内核中
 * @param       [in]   *obj      状态机对象
 * @return      [out]  void
 * @note        None
 */
void sm_obj_remove(sm_obj_t *obj)
{
    SM_ASSERT(obj);

    sm_list_remove(&obj->list);

    if (obj->attribute.is_dynamic)
    {
        SM_FREE(obj);
    }
}

/**
 *******************************************************************************
 * @brief       状态机对象SELF TIMER 操作接口
 *******************************************************************************
 */
static void _self_timer_init(void)
{
    sm_timer_stop(&sm_self_obj()->timer);
}

static void _self_timer_start(uint16_t evt, sm_tick_t tick)
{
    sm_timer_start(&sm_self_obj()->timer, sm_self_obj(), evt, tick);
}

static void _self_timer_stop(void)
{
    sm_timer_stop(&sm_self_obj()->timer);
}

/**
 *******************************************************************************
 * @brief       状态机对象SELF EVENT 操作接口
 *******************************************************************************
 */
static void _self_flag_init(void)
{
    sm_event_flag_init(&sm_self_obj()->event_flag);
}

static void _self_flag_send(uint32_t set)
{
    sm_event_flag_send(&sm_self_obj()->event_flag, set);
}

static void _self_flag_filter_append(uint32_t recv, uint32_t flag, sm_obj_t *obj, uint16_t trig)
{
    sm_event_flag_filter_t *filter = (sm_event_flag_filter_t *)SM_MALLOC(sizeof(sm_event_flag_filter_t));
    SM_ASSERT(filter);

    sm_event_flag_filter_append(&sm_self_obj()->event_flag, filter, recv, flag, obj, trig);
}

static void _self_flag_filter_append_static(sm_event_flag_filter_t *filter, uint32_t recv, uint32_t flag, sm_obj_t *obj, uint16_t trig)
{
    sm_event_flag_filter_append(&sm_self_obj()->event_flag, filter, recv, flag, obj, trig);
}

static void _self_flag_filter_clear(void)
{
    sm_event_flag_filter_clear(&sm_self_obj()->event_flag);
}

/**
 *******************************************************************************
 * @brief       状态机对象SELF SIGNAL 操作接口
 *******************************************************************************
 */

/**
 *******************************************************************************
 * @brief       状态机状态迁移动作接口
 *******************************************************************************
 */
/**
 * @brief       状态机状态迁移处理函数
 * @param       [in]   *me     状态机对象
 * @return      [out]  ret     状态机迁移结果
 * @note        None
 */
static inline
uint8_t sm_tran_process(sm_obj_t *me)
{
#ifdef STATE_MACHINE_CORE_LOG_CONSOLE
    LOG_I("[SM TRAN][%s]Exit Current State", sm_obj_name(me));
#endif

    //! 退出当前状态
    me->state(me, &(sm_msg_t){.sig = SM_EXIT_EVENT});

#ifdef STATE_MACHINE_CORE_LOG_CONSOLE
    LOG_I("[SM TRAN][%s]Enter New State", sm_obj_name(me));
#endif
    
    //! 进入新状态
    uint8_t ret = me->temp(me, &(sm_msg_t){.sig = SM_ENTRY_EVENT});

    me->state   = me->temp;

    return ret;
}

/**
 * @brief       状态机状态回退处理函数
 * @param       [in]   *me     状态机对象
 * @return      [out]  ret     状态机迁移结果
 * @note        None
 */
static inline
uint8_t sm_back_process(sm_obj_t *me)
{
    uint8_t ret = me->state(me, &(sm_msg_t){.sig = SM_EXIT_EVENT});

    me->state   = me->temp;
    
    return ret;
}

/**
 * @brief       状态机退出子状态处理函数
 * @param       [in]   *me     状态机对象
 * @param       [in]   now     状态机当前状态
 * @param       [in]   page    状态机页状态
 * @return      [out]  ret     状态机迁移结果
 * @note        None
 */
static inline
uint8_t sm_exit_sub_process(sm_obj_t *me, sm_state_f now, sm_state_f page)
{
    uint8_t ret;
    sm_msg_t msg;
    
    sm_state_f temp = page;
    
    while(1)
    {
        //! 退出当前状态
        msg.sig = SM_EXIT_EVENT;

        ret = temp(me, &msg);
        
        if (me->temp == now)
        {
            break;
        }
        
        temp = me->temp;
    }
    
    return ret;
}

/* Exported functions --------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief       SM CORE操作接口
 *******************************************************************************
 */
/**
 * @brief       状态机组件内核初始化函数
 * @param       [in]   *handle      状态机内核管理句柄
 * @return      [out]  0
 * @note        None
 */
uint8_t sm_core_init(struct SM_CORE_HANDLE *handle)
{
    SM_ASSERT(handle);

    //! define sm self handle
    static sm_self_t sm_self;

     //! define timer ops
    static const struct SM_SELF_TIMER_OPS timerOps = SM_TIMER_OPS_INIT_PARAM;

    //! define flag ops
    static const struct SM_SELF_EVENT_FLAG_OPS flagOps = SM_EVENT_FLAG_OPS_INIT_PARAM;

    //! define sig ops
    static const struct SM_SELF_SIGNAL_OPS sigOps = SM_SIGNAL_OPS_INIT_PARAM;

    //! clear handle memory data
    memset(handle, 0, sizeof(struct SM_CORE_HANDLE));
    
    //! clear sm self memory data
    memset(&sm_self, 0, sizeof(sm_self));

    //! init sm self object
    sm_self.timer = &timerOps;
    sm_self.flag  = &flagOps;
    sm_self.sig   = &sigOps;
    handle->self  = &sm_self;

    //! init sm core object list
    sm_list_init(&handle->obj_list);

    //! init sm core timer list
    sm_list_init(&handle->timer_list);

    return 0;
}

/**
 * @brief       状态机组件内核处理函数
 * @param       [in]   *me      状态机对象句柄
 * @param       [in]   *msg     消息
 * @return      [out]  void
 * @note        None
 */
uint8_t sm_core_process(sm_obj_t *me, sm_msg_t *msg)
{
    uint8_t status = 0;
    
    SM_ASSERT(msg);
    
    //! 获取状态机句柄
    if (IS_PTR_NULL(me))
    {
        me = (sm_obj_t *)msg->obj;

        if (IS_PTR_NULL(me))
        {
            SM_ERR("Get Sm Handle Failed");
            return 1;
        }
        else
        {
            sm_core()->self->obj = me;
        }
	}

    uint8_t ret;
    
    void *ptr = (void *)me->state;

    //! 检查状态机是否已经初始化
    if (!me->attribute.is_init)
    {
        return 1;
    }

    while (1)
    {
        sm_core()->self->obj = me;
        
        //! 遍历状态表
        ret = sm_fsm_table_process(me, msg);
        ret = ret == SM_RET_UNHANDLED ? me->state(me, msg) : SM_RET_HANDLED;

__SM_RET_HANDLE:
        //! 状态转移处理
        if (ret == SM_RET_TRAN)
        {
            ret = sm_tran_process(me);
            
            ptr = (void *)me->state;
            
            goto __SM_RET_HANDLE;
        }
        //! 等待处理
        else if (ret == SM_RET_WAIT)
        {
            status = 0;
            break;
        }
        //! 父状态处理
        else if (ret == SM_RET_SUPER)
        {
            me = (sm_obj_t *)me->super;
        }
        //! 子状态返回处理
        else if (ret == SM_RET_BACK)
        {
            ret = sm_back_process(me);

            ptr = (void *)me->state;

            goto __SM_RET_HANDLE;
        }
        //! 子状态退出
        else if (ret == SM_RET_EXIT_SUB)
        {
            sm_exit_sub_process(me, me->state, (sm_state_f)ptr);
            ptr = (void *)me->state;
            
            break;
        }
        //! 其他状态处理
        else
        {
            status = 1;
            break;
        }
    }
    
    me->state = (sm_state_f)ptr;
    
    return status;
}

/**
 *******************************************************************************
 * @brief       SM SELF 操作接口
 *******************************************************************************
 */
/**
 * @brief       获取SM SELF句柄
 * @param       [in]   void
 * @return      [out]  SM 对象句柄
 * @note        sm component内部调用
 */
sm_self_t *sm_self(void)
{
    return sm_core()->self;
}

/**
 * @brief       获取SM对象句柄
 * @param       [in]   void
 * @return      [out]  SM 对象句柄
 * @note        sm component内部调用
 */
sm_obj_t *sm_self_obj(void)
{
    return sm_core()->self->obj;
}

/**
 *******************************************************************************
 * @brief       SM OBJ操作接口
 *******************************************************************************
 */
/**
 * @brief       状态机对象初始化函数
 * @param       [in]   id        状态机ID
 * @param       [in]   init      状态机初始状态
 * @param       [in]   *param    拓展参数
 * @return      [out]  void
 * @note        None
 */
void sm_obj_init(sm_obj_t *me, char *name, sm_state_f init)
{
//    //! get sm object
//	sm_obj_t *me = sm_obj_find(name);

    //! memory init
    memset(me, 0, sizeof(sm_obj_t));

    //! 初始化属性信息
    me->super = NULL;

    //! 配置设备名称
    sm_parent_init(me, name);

    //! 初始化sm list
    sm_list_init(&me->list);

    //! 将状态机对象挂载到内核中
    sm_obj_append(me);

    //! 初始化事件组件
    sm_list_init(&me->event_flag_list);

    //! 初始化信号组件
    sm_list_init(&me->sig_list);

    //! 初始化定时器组件
    sm_timer_init(&me->timer);

    //! 设置临时状态机
    sm_core()->self->obj = me;

    //! 初始化状态机
    me->temp  = init;

#ifdef STATE_MACHINE_CORE_LOG_CONSOLE
    LOG_I("[SM][%s]State Mechine Init", sm_obj_name(me));
#endif

    //! 状态机初始化
    me->temp(me, &(sm_msg_t){.obj=0, .sig=SM_INIT_EVENT});
    me->temp(me, &(sm_msg_t){.obj=0, .sig=SM_ENTRY_EVENT});

    //! 更新状态信息
    me->state = me->temp;

    //! 设置初始化标志
    me->attribute.is_init = 1;
}

/**
 * @brief       状态机对象创建并初始化函数
 * @param       [in]   id        状态机ID
 * @param       [in]   init      状态机初始状态
 * @param       [in]   *param    拓展参数
 * @return      [out]  void
 * @note        该API已弃用，SM对象不允许动态创建
 */
sm_obj_t *sm_obj_create(char *name, sm_state_f init)
{
    //! alloc memory area
    sm_obj_t *me = SM_MALLOC(sizeof(sm_obj_t));
    SM_ASSERT(me);

    //! state mechine object init
    sm_obj_init(me, name, init);

    //! set state mechine object memory dynamic attribute
    me->attribute.is_dynamic = 1;

    return me;
}

/**
 * @brief       状态机对象销毁函数
 * @param       [in]   id      状态机ID
 * @return      [out]  void
 * @note        None
 */
void sm_obj_delete(char *name)
{
    sm_obj_t *me = sm_obj_find(name);

    if (!IS_PTR_NULL(me))
    {
        sm_obj_remove(me);
    }
}

/**
 *******************************************************************************
 * @brief       SM TIMER操作接口
 *******************************************************************************
 */
/**
 * @brief       定时器初始化函数
 * @param       [in]   *timer    定时器句柄
 * @return      [out]  void
 * @note        extern
 */
void sm_timer_init(sm_timer_t *timer)
{
    sm_list_init(&timer->list);

    sm_timer_stop(timer);
}

/**
 * @brief       定时器启动函数
 * @param       [in]   *timer    定时器句柄
 * @param       [in]   *obj      SM对象
 * @param       [in]   evt       定时器超时完成事件
 * @param       [in]   tick      定时器超时时间
 * @return      [out]  void
 * @note        extern
 */
void sm_timer_start(sm_timer_t *timer, sm_obj_t *obj, uint16_t evt, sm_tick_t tick)
{
    sm_timer_stop(timer);
    
    if (tick == 0)
    {
        sm_msg_post(obj, evt, NULL);
    }
    else
    {
        timer->attribute.obj   = (struct SM_OBJECT *)obj;
        timer->attribute.trig  = evt;

        timer->attribute.tick  = tick;
        timer->attribute.state = 1;

        sm_list_append(&sm_core()->timer_list, &timer->list);
    }
}

/**
 * @brief       定时器停止函数
 * @param       [in]   *timer    定时器句柄
 * @return      [out]  void
 * @note        extern
 */
void sm_timer_stop(sm_timer_t *timer)
{
    sm_list_remove(&timer->list);

    memset(&timer->attribute, 0, sizeof(timer->attribute));
}

/**
 * @brief       定时器组件处理函数
 * @param       [in]   *handle   状态机句柄
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_timer_process(struct SM_CORE_HANDLE *handle)
{
    sm_tick_t cur  = sm_tick_get();
    sm_tick_t past = (cur >= handle->last_tick) ? 
        (cur - handle->last_tick) : (SM_TICK_MAX - handle->last_tick + cur);

    handle->last_tick   = cur;

    sm_list_for_each_entry(timer, &handle->timer_list, sm_timer_t, list)
    {
        if (timer->attribute.state)
        {
            if (past >= timer->attribute.tick)
            {
                timer->attribute.state = 0;
                timer->attribute.tick  = 0;

                sm_list_remove(&timer->list);
                sm_msg_post(timer->attribute.obj, timer->attribute.trig, NULL);
            }
            else
            {
                timer->attribute.tick -= past;
            }
        }
    }
}

/**
 * @brief       定时器初始化函数
 * @param       [in]   *timer    定时器句柄
 * @return      [out]  void
 * @note        extern
 */
void sm_self_timer_init(void)
{
    sm_timer_init(&sm_self_obj()->timer);
}

/**
 * @brief       定时器启动函数
 * @param       [in]   *timer    定时器句柄
 * @param       [in]   *obj      SM对象
 * @param       [in]   evt       定时器超时完成事件
 * @param       [in]   tick      定时器超时时间
 * @return      [out]  void
 * @note        extern
 */
void sm_self_timer_start(uint16_t evt, sm_tick_t tick)
{
    sm_timer_start(&sm_self_obj()->timer, sm_self_obj(), evt, tick);
}

/**
 * @brief       定时器停止函数
 * @param       [in]   *timer    定时器句柄
 * @return      [out]  void
 * @note        extern
 */
void sm_self_timer_stop(void)
{
    sm_timer_stop(&sm_self_obj()->timer);
}

/**
 *******************************************************************************
 * @brief       SM EVENT FLAG 操作接口
 *******************************************************************************
 */
/**
 * @brief       状态机事件初始化
 * @param       [in]   *evt      事件组句柄
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_event_flag_init(sm_event_flag_t *evt)
{
    evt->set = 0;
    
    sm_list_init(&evt->list);
}

/**
 * @brief       状态机事件发送函数
 * @param       [in]   *evt      事件组句柄
 * @param       [in]   set       设置事件
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_event_flag_send(sm_event_flag_t *evt, uint32_t set)
{
    uint8_t status = 0;

    evt->set |= set;

    sm_list_for_each_entry(filter, &evt->list, sm_event_flag_filter_t, list)
    {
        if (filter->attribute.flag & SM_EVENT_FILTER_AND)
        {
            if ((evt->set & filter->attribute.get) == filter->attribute.get)
            {
                status = 1;
            }
        }
        else if (filter->attribute.flag & SM_EVENT_FILTER_OR)
        {
            if (evt->set & filter->attribute.get)
            {
                status = 1;
            }
        }

        if (status)
        {
            if (filter->attribute.flag & SM_EVENT_FILTER_CLEAR)
            {
                evt->set &= ~filter->attribute.get;
            }

            sm_msg_post(filter->attribute.obj, filter->attribute.trig, NULL);
        }
    }
}

/**
 * @brief       状态机事件设置过滤器函数
 * @param       [in]   *evt      事件组句柄
 * @param       [in]   set       设置事件
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_event_flag_filter_init(sm_event_flag_filter_t *filter)
{
    sm_list_init(&filter->list);

    memset(&filter->attribute, 0, sizeof(filter->attribute));
}

/**
 * @brief       状态机事件组清除过滤器函数
 * @param       [in]   *filter   事件组过滤器句柄
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_event_flag_filter_clear(sm_event_flag_t *evt)
{
    sm_list_for_each_entry(filter, &evt->list, sm_event_flag_filter_t, list)
    {
        sm_event_flag_filter_remove(filter);
    }
}

/**
 * @brief       状态机事件组移除过滤器函数
 * @param       [in]   *filter   事件组过滤器句柄
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_event_flag_filter_remove(sm_event_flag_filter_t *filter)
{
    sm_list_remove(&filter->list);

    memset(&filter->attribute, 0, sizeof(filter->attribute));
}

/**
 * @brief       状态机事件组设置过滤器函数
 * @param       [in]   *evt      事件组句柄
 * @param       [in]   *filter   事件组过滤器句柄
 * @param       [in]   recv      接受方事件
 * @param       [in]   flag      过滤器参数
 * @param       [in]   obj       接收方对象ID
 * @param       [in]   trig      接收方触发事件
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_event_flag_filter_append(sm_event_flag_t *evt, 
                                 sm_event_flag_filter_t *filter, 
								 uint32_t recv, uint32_t flag, 
                                 sm_obj_t *obj, uint32_t trig)
{
    sm_event_flag_filter_remove(filter);
    
    filter->attribute.get  = recv;
    filter->attribute.flag = flag;
    filter->attribute.obj  = (struct SM_OBJECT *)obj;
    filter->attribute.trig = trig;

    sm_list_append(&evt->list, &filter->list);
}

/**
 *******************************************************************************
 * @brief       SM SIGNAL 操作接口
 *******************************************************************************
 */
/**
 * @brief       状态机信号初始化
 * @param       [in]   *sig      事件组句柄
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_sig_init(sm_sig_t *sig)
{
    SM_ASSERT(sig);
    
    sm_list_init(&sig->list);
}

/**
 * @brief       状态机信号注销
 * @param       [in]   *sig      事件组句柄
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_sig_fini(sm_sig_t *sig)
{
    SM_ASSERT(sig);

    sm_list_for_each_entry(slot, &sig->list, sm_slot_t, list)
    {
        SM_ASSERT(slot);

        sm_sig_disconnect(slot);
    }

    sm_list_init(&sig->list);
}

/**
 * @brief       状态机信号发射函数
 * @param       [in]   *sig      事件组句柄
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_sig_emit(sm_sig_t *sig)
{
    SM_ASSERT(sig);

    sm_list_for_each_entry(slot, &sig->list, sm_slot_t, list)
    {
        SM_ASSERT(slot);

        if (slot->is_trig_message)
        {
            sm_msg_post(slot->obj, slot->trig, NULL);
        }
        else if (slot->is_trig_callback)
        {
            FUNC_S(slot->callback, slot->param);
        }
    }
}

/**
 * @brief       状态机信号连接函数
 * @param       [in]   *sig      事件组句柄
 * @param       [in]   *slot     槽句柄
 * @param       [in]   obj       接收方对象ID
 * @param       [in]   trig      接收方触发事件
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_sig_connect_event_static(sm_sig_t *sig, sm_slot_t *slot, sm_obj_t *obj, uint16_t trig)
{
    SM_ASSERT(sig);
    SM_ASSERT(slot);

    //! init memory
    memset(slot, 0, sizeof(sm_slot_t));
    
    //! set memory type
    slot->is_dynamic = 1;
    
    //! set trigger type
    slot->is_trig_callback = 0;
    slot->is_trig_message  = 1;
    
    //! set slot object
    slot->obj  = (struct SM_OBJECT *)obj;
    slot->trig = trig;

    //! add to sig list
    sm_list_append(&sig->list, &slot->list);
}

/**
 * @brief       状态机信号连接函数
 * @param       [in]   *sig      事件组句柄
 * @param       [in]   obj       接收方对象ID
 * @param       [in]   trig      接收方触发事件
 * @return      [out]  void
 * @note        sm component内部调用
 */
sm_slot_t *sm_sig_connect_event(sm_sig_t *sig, sm_obj_t *obj, uint16_t trig)
{
    //! ALLOC SLOT MEMORY
    sm_slot_t *slot = (sm_slot_t *)SM_MALLOC(sizeof(sm_slot_t));
    SM_ASSERT(slot);

    //! init memory
    memset(slot, 0, sizeof(sm_slot_t));
    
    //! connect
    sm_sig_connect_event_static(sig, slot, obj, trig);

    return slot;
}

/**
 * @brief       状态机信号连接函数
 * @param       [in]   *sig      事件组句柄
 * @param       [in]   *slot     槽句柄
 * @param       [in]   *cb       回调函数指针
 * @param       [in]   *param    回调函数参数
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_sig_connect_callback_static(sm_sig_t *sig, sm_slot_t *slot, void *cb, void *param)
{
    SM_ASSERT(sig);
    SM_ASSERT(slot);

    //! set memory type
    slot->is_dynamic = 1;
    
    //! set trigger type
    slot->is_trig_callback = 1;
    slot->is_trig_message  = 0;
    
    //! set slot object
    slot->callback = (void (*)(void *))cb;
    slot->param    = param;

    //! add to sig list
    sm_list_append(&sig->list, &slot->list);
}

/**
 * @brief       状态机信号连接函数
 * @param       [in]   *sig      事件组句柄
 * @param       [in]   *cb       回调函数指针
 * @param       [in]   *param    回调函数参数
 * @return      [out]  void
 * @note        sm component内部调用
 */
sm_slot_t *sm_sig_connect_callback(sm_sig_t *sig, void *cb, void *param)
{
    //! ALLOC SLOT MEMORY
    sm_slot_t *slot = (sm_slot_t *)SM_MALLOC(sizeof(sm_slot_t));
    SM_ASSERT(slot);
    
    //! init memory
    memset(slot, 0, sizeof(sm_slot_t));

    //! connect
    sm_sig_connect_callback_static(sig, slot, cb, param);

    return slot;
}

/**
 * @brief       状态机信号槽断开函数
 * @param       [in]   *slot     槽句柄
 * @return      [out]  void
 * @note        sm component内部调用
 */
void sm_sig_disconnect(sm_slot_t *slot)
{
    SM_ASSERT(slot);

    sm_list_remove(&slot->list);
    
    if (slot->is_dynamic)
    {
        SM_FREE(slot);
    }
}

/**
 *******************************************************************************
 * @brief       SM FSM TABLE操作接口
 *******************************************************************************
 */
/**
 * @brief       fsm table 初始化函数
 * @param       [in]   *table       状态表
 * @param       [in]   *len         状态表长度
 * @param       [in]   *callback    状态表回调函数
 * @return      [out]  void
 * @note        extern
 */
void sm_fsm_table_mnt(const sm_fsm_table_t *table, 
                      uint32_t len,
                      sm_fsm_table_ret_t (*callback)(struct SM_OBJECT*, const struct FSM_TABLE*, sm_msg_t *msg))
{
    sm_obj_t *me = sm_self_obj();
    sm_table_handle_t *handle = &me->fsm_table;

    handle->state    = 0;
    handle->len      = len;
    handle->buffer   = table;
    handle->callback = callback;

//    sm_fsm_table_process(me, &(sm_msg_t){me, 0, SM_FSMTABLE_ENTRY_EVENT, 0});

//    FUNC_S(handle->callback, me, NULL, );

    sm_msg_post(me, SM_FSMTABLE_ENTRY_EVENT, 0);
}

/**
 * @brief       fsm table 结束函数
 * @param       [in]   void
 * @return      [out]  void
 * @note        extern
 */
void sm_fsm_table_unmnt(void)
{
    sm_obj_t *me = sm_self_obj();
    sm_table_handle_t *handle = &me->fsm_table;

    FUNC_S(handle->callback, me, NULL, &(sm_msg_t){me, 0, SM_FSMTABLE_EXIT_EVENT, 0});

    handle->state    = 0;
    handle->len      = 0;
    handle->buffer   = NULL;
    handle->callback = NULL;
}

/**
 * @brief       fsm table 处理函数
 * @param       [in]   *me     状态机对象
 * @param       [in]   *msg    消息信息
 * @return      [out]  void
 * @note        extern
 */
uint8_t sm_fsm_table_process(sm_obj_t *me, sm_msg_t *msg)
{
    sm_table_handle_t *handle = &me->fsm_table;

    uint8_t ret = SM_UNHANDLED();

    //! 检查状态表信息
    if (IS_PTR_NULL(handle->buffer))
    {
//        LOG_W("[%s]fsm table is empty", sm_obj_name(me));
        return SM_UNHANDLED();
    }

    for (uint32_t i=0; i<handle->len; i++)
    {
        const sm_fsm_table_t *tab = &handle->buffer[i];

        uint32_t cur_state = tab->cur_state & tab->state_mask;
        if (cur_state == handle->state && tab->in_event == msg->sig)
        {
            //! update process state
            ret = SM_HANDLE();

            //! state mechine table callback process
            sm_fsm_table_ret_t cb_out = FUNC_RET_CS(((sm_fsm_table_ret_t){0, 0}), me->fsm_table.callback, me, tab, msg);

            //! update state mechine table out event
            uint32_t out_event = cb_out.out_event ? cb_out.out_event : tab->out_event;

            //! update state mechine state code
            handle->state = cb_out.tran_state ? cb_out.tran_state : tab->tran_state;

            //! output event process
            if (out_event != SM_EMPTY_EVENT)
            {
                msg->sig = (enum SM_EVENT_DEFINE)out_event;

                ret = SM_UNHANDLED();

                //! todo: new version add it
//                if (out_event == SM_FSMTABLE_EXIT_EVENT)
//                {
//                    sm_fsm_table_unmnt();
//                    break;
//                }
            }

            break;
        }
    }

    return ret;
}

/** @}*/     /** framework state machine component */

/**********************************END OF FILE*********************************/
